home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c++-part1 / 9585 < prev    next >
Encoding:
Text File  |  1996-08-05  |  4.7 KB  |  134 lines

  1. Path: news.belwue.de!uzwil!kuehl
  2. From: kuehl@uzwil.informatik.uni-konstanz.de (Dietmar Kuehl)
  3. Newsgroups: comp.lang.c++,gnu.g++.help
  4. Subject: Re: DONT UNDERSTAND - array of char error
  5. Followup-To: comp.lang.c++,gnu.g++.help
  6. Date: 2 Mar 1996 22:20:46 GMT
  7. Organization: FakultΣt fⁿr Mathematik und Informatik
  8. Message-ID: <4hahju$bil@news.BelWue.DE>
  9. References: <4habvu$99j@panix.com>
  10. Reply-To: dietmar.kuehl@uni-konstanz.de
  11. NNTP-Posting-Host: uzwil.informatik.uni-konstanz.de
  12. X-Newsreader: TIN [version 1.2 PL2]
  13.  
  14. Hi,
  15. Arthur Cinader Jr (acinader@panix.com) wrote:
  16. :     char *labels[];
  17. :     char *params[];
  18.  
  19. : the compiler, g++, gave me the following error:
  20.  
  21. :     param.h:21: field `labels' has incomplete type
  22.  
  23. : I don't understand why this doesn't work.  
  24.  
  25. You want to allocate an object whose size is unknown. This is always
  26. impossible in C++. You can, however, pass around "handle" to an object
  27. whose size is unknown, e.g. a pointer to an array:
  28.  
  29.   void foo(char *argv[]) {} // legal
  30.  
  31. If you want to actually allocate an object, the size of the object has
  32. to be known, e.g. in a definition like this:
  33.   
  34.   const int size = 17;
  35.   char *labels[size];
  36.  
  37. where 'size' is always a constant expression (i.e. it is NOT possible
  38. to use some variable for size, whose value is determined at run-time).
  39.  
  40. : In any event, I changed the declaration to:
  41.  
  42. :     char **labels;
  43. :     char **params;
  44.  
  45. : Which the compiler liked.
  46.  
  47. Sure, because it knows the size of the object: a pointer to pointer to
  48. 'char' is probably four bytes (you can use 'sizeof(char**)' to find
  49. out).
  50.  
  51. : Now, I am unable to new the arrays.
  52.  
  53. Well, because you forgot about an important restriction on arrays: All
  54. but the first dimension has to be fixed at compile-time.
  55.  
  56. : In the definition (.C) file, I use the comand:
  57.  
  58. :     labels = new char[maxargs][fieldlength]; // make label array
  59. :     params = new char[maxargs][fieldlength]; // make params array
  60.  
  61. ... i.e. 'fieldlength' has to be a 'const'. If 'fieldlength' is
  62. non-const you have to allocate the second dimension by hand (unless you
  63. use an array class like suggested below):
  64.  
  65.   lables = new char *[maxargs]; // it is valid to allocate an array
  66.   params = new char *[maxargs]; // of 'char*'
  67.   for (int i = 0; i < maxargs; i++)
  68.   {
  69.     labels[i] = new char[fieldlength]; // ... and to allocate an
  70.     params[i] = new char[fieldlength]; // of 'char'.
  71.   }
  72.  
  73. ... but an array thus create has to be destructed like this:
  74.  
  75.   for (int i = maxargs; i--; )
  76.   {
  77.     delete[] params[i];
  78.     delete[] lables[i];
  79.   }
  80.   delete params;
  81.   delete lables;
  82.  
  83. Which is, IMHO, far to dangerous to be done: Given that you run out of
  84. memory, you are likely to end up with a serious memory-leak. I know how
  85. to program in C++ and I won't do it like this... This is exactly the
  86. problem I have with all C++ tutorials I have seen until know: They
  87. introduce the low-level methods, requiring to be an expert to handle
  88. them correctly, but they don't introduce the clean methods provided by
  89. the (upcoming) ISO Standard C++ Library (to be fair: this library was
  90. introduced into the standard quite recently, i.e. sometime in 1994). A
  91. clean method is to use the 'vector' class found in libg++ starting with
  92. libg++-2.6.? (you didn't mention what version you are using but I
  93. assume a recent one, e.g. 2.7.2):
  94.  
  95.   void f(int maxargs, int fieldlength)
  96.   {
  97.     vector<vector<char> > labels(maxargs, vector<char>(fieldlength));
  98.     vector<vector<char> > labels(maxargs, vector<char>(fieldlength));
  99.     // ...
  100.     // Note that the compiler takes care of destruction...
  101.   }
  102.  
  103. It is even possible to resize these 'vector' (something impossible with
  104. built-in arrays). I suggest, that you use 'vector' instead of built-in
  105. arrays...
  106.  
  107. : The compiler complains with the following:
  108.  
  109. :     param.C: In method `Param::Param(char *)':
  110. :     param.C:11: assignment to `char **' from `char (*)[1]'
  111. :     param.C:16: assignment to `char **' from `char (*)[1]'
  112.  
  113. : I do not understand why?
  114.  
  115. Well, the compiler knows that he can only allocate an array with one
  116. dimension being variable i.e. it assumes that 'char[maxargs]' is a type
  117. (the '[fieldlength]' could not be append and the stuff still be a type)
  118. and thus interprets the expression 'new char[maxargs][fieldlength]' as
  119. '(new char[maxargs])[fieldlength]'. This allocates an array of 'char'
  120. and applies the "index operator" ([]) to it with 'fieldlength' as
  121. arguemtn. Thus the value of the whole expression is the 'fieldlength`'
  122. element of the just allocated array. This is, probably, not what you
  123. want...
  124.  
  125. : P.S. do the deletes in my destructor look kosher?
  126.  
  127. Well, it is only half the way to be done... See my code example above
  128. for a complete deallocation of a hand-crafted two-dimensional array
  129. with variable bounds.
  130. --
  131. dietmar.kuehl@uni-konstanz.de
  132. http://www.informatik.uni-konstanz.de/~kuehl
  133. I am a realistic optimist - that's why I appear to be slightly pessimistic
  134.